﻿using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using MS.Core.Configuration;
using MS.Core.Model;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;

namespace MS.Core.Helper
{
    /// <summary>
    /// Token的帮助类
    /// </summary>
    public class TokenHelper
    {
        private readonly JwtSettings _jwtSettings;

        public TokenHelper()
        {
            _jwtSettings = AppSettingHelper.GetModel<JwtSettings>("JwtSettings");
        }

        /// <summary>
        /// 颁发Token
        /// </summary>
        /// <returns></returns>
        public ResponseToken CreateToken(string id ,string name)
        {
           
            List<Claim> claims = new List<Claim>()
            {
                new Claim(ClaimTypes.NameIdentifier, id),
                new Claim(ClaimTypes.Name, name)
            };

            string key = _jwtSettings.SecrentKey;

            DateTime now = DateTime.Now;

            var expores = now.AddMinutes(_jwtSettings.Expirces);

            byte[] secBytes = Encoding.UTF8.GetBytes(key);
            var secKey = new SymmetricSecurityKey(secBytes);
            var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);

            var tokenDescriptor = new JwtSecurityToken(
                issuer: _jwtSettings.Issuer,
                audience: _jwtSettings.Audience,
                claims: claims,
                notBefore: now,
                expires: expores,
                signingCredentials: credentials);


            string token = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
            string refreshToken = CreateRefreshToken();

            //需要将两个Token 都放在缓存中

            return new ResponseToken() { accessToken = token, RefreshToken = refreshToken };
        }

        /// <summary>
        /// 生成refresh_Token
        /// </summary>
        /// <returns></returns>
        public string CreateRefreshToken()
        {
            var refresh = new byte[32];
            using (var number = RandomNumberGenerator.Create())
            {
                number.GetBytes(refresh);
                return Convert.ToBase64String(refresh);
            }

            //将refresh_Token存在缓存中
        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="Token"></param>
        /// <param name="refresh_Token"></param>
        /// <returns></returns>
        /// <exception cref="SecurityTokenException"></exception>
        public ResponseToken Refresh(string Token, string refresh_Token)
        {
            string key = _jwtSettings.SecrentKey;

            byte[] secBytes = Encoding.UTF8.GetBytes(key);
            var secKey = new SymmetricSecurityKey(secBytes);

            var tokenHandler = new JwtSecurityTokenHandler();
            SecurityToken validatedToken;

            // 根据过期Token获取一个SecurityToken
            var principal = tokenHandler.ValidateToken(Token, new TokenValidationParameters()
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = secKey,
                ValidateIssuer = true,
                ValidIssuer = _jwtSettings.Issuer,
                ValidateAudience = true,
                ValidAudience = _jwtSettings.Audience,
                ValidateLifetime = false
            }, out validatedToken);

            var jwtToken = validatedToken as JwtSecurityToken;

            if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256Signature, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new SecurityTokenException("Token不合法");
            }

            //判断refresh_Token是否此用户生成的

            //生成新Token
            List<Claim> claims = new List<Claim>()
            {
                new Claim(ClaimTypes.NameIdentifier, "1"),
                new Claim(ClaimTypes.Name, "jjm")
            };

            var jwtSecurityToken = new JwtSecurityToken(
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddMinutes(_jwtSettings.Expirces),
                issuer: _jwtSettings.Issuer,
                audience: _jwtSettings.Audience,
                signingCredentials: new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature)
                );

            var token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
            var refreshToken = CreateRefreshToken();

            //将缓存中原来的Token和refresh_Token 删除掉，并且保存新生成的Token

            return new ResponseToken() { accessToken = token, RefreshToken = refreshToken };
        }
    } 
}
